package com.jy.adscm.declarationForm.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.jy.adscm.bean.system.JyCode;
import com.jy.adscm.bean.system.JyCodeType;
import com.jy.adscm.bean.system.JyUser;
import com.jy.adscm.dealer.bean.Dealer;
import com.jy.adscm.dealer.mapper.DealerMapper;
import com.jy.adscm.declarationForm.bean.JyDeclarationForm;
import com.jy.adscm.declarationForm.mapper.JyDeclarationFormMapper;
import com.jy.adscm.declarationForm.service.JyDeclarationFormService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.jy.adscm.exception.AdscmSystemException;
import com.jy.adscm.hospital.bean.JyHospitalBase;
import com.jy.adscm.hospital.mapper.JyHospitalBaseMapper;
import com.jy.adscm.security.utils.AdscmSecurityUtils;
import com.jy.adscm.support.SimpleCoreResponse;
import com.jy.adscm.system.mapper.mysql.JyCodeMapper;
import com.jy.adscm.system.mapper.mysql.JyCodeTypeMapper;
import com.jy.adscm.system.mapper.mysql.JyUserMapper;
import com.jy.adscm.utils.AdscmBaseUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 经销商报单表 服务实现类
 * </p>
 *
 * @author yyy
 * @since 2019-01-21
 */
@Service
public class JyDeclarationFormServiceImpl extends ServiceImpl<JyDeclarationFormMapper, JyDeclarationForm> implements JyDeclarationFormService {

    private Logger logger = Logger.getLogger(getClass());

    @Autowired
    JyDeclarationFormMapper jyDeclarationFormMapper;
    @Autowired
    JyHospitalBaseMapper jyHospitalBaseMapper;

    @Autowired
    JyUserMapper jyUserMapper;

    @Autowired
    DealerMapper dealerMapper;

    @Autowired
    JyCodeMapper jyCodeMapper;
    @Autowired
    JyCodeTypeMapper jyCodeTypeMapper;




    @Override
    public void addDeclarationForm(JyUser user, JyDeclarationForm jyDeclarationForm) throws AdscmSystemException  {

        logger.info("增加报单申请");

        //查询下报单状态，如果当前医院的当前科室已经被其他经销商报单了，那么直接将报单申请丢入意向队列中   前段查询了状态后传过来
//        jyDeclarationForm.setApplyStatus(queryApplyStatus(jyDeclarationForm) + "");//申请状态 0:待审核 , 4 :意向队列

        if (jyDeclarationForm.getApplyHospitalName() == null || "".equals(jyDeclarationForm.getApplyHospitalName())){
            throw new AdscmSystemException("参数为NULL，申请失败！");
        }

        Integer unitId = user.getUnitId();
        jyDeclarationForm.setApplyDealerId(unitId);
        jyDeclarationForm.setApplyDealerUserId(user.getId());
        jyDeclarationForm.setApplyTime(new Date());
        if(jyDeclarationForm.getApplyStatus() != null && jyDeclarationForm.getApplyStatus() > 0){
        }else {
            jyDeclarationForm.setApplyStatus(0);
        }
        jyDeclarationForm.setEarlyWarning(0);//未预警
        jyDeclarationFormMapper.insert(jyDeclarationForm);
    }

    @Override
    public List<JyDeclarationForm> queryApplyByDealerId(List<Integer> dealerIds,int isYix) {

        logger.info("查询经销商【"+dealerIds+"】的报单申请列表");

        return jyDeclarationFormMapper.queryApplyByDealerId(dealerIds,isYix);
    }

    @Override
    public List<JyDeclarationForm> queryHospitalDeclarationFormDetail(Long hospitalId) {

        logger.info("查询医院【"+ hospitalId +"】的所有报单详情");

        return jyDeclarationFormMapper.queryHospitalDeclarationFormDetail(hospitalId);
    }

    @Override
    public JyDeclarationForm queryDealerApplyFormDetail(Long declarationFormId) {

        logger.info("查询报单详情");

        JyDeclarationForm form = jyDeclarationFormMapper.selectById(declarationFormId);

        if (form != null){
            JyCodeType codeType = null;
            JyCode entity = null;
            JyCode jyCode = null;

            //医院类别
            if(form.getApplyHospitalType() != null){

                codeType = new JyCodeType();
                codeType.setType("hospital_type");
                JyCodeType hospitalType = jyCodeTypeMapper.selectOne(codeType);

                entity = new JyCode();
                entity.setType(hospitalType.getId());
                entity.setCode(form.getApplyHospitalType().toString());
                jyCode = jyCodeMapper.selectOne(entity);
                form.setApplyHospitalTypeDesc(jyCode.getName());
            }

            //医院级别
            if(form.getApplyHospitalLevel() != null){

                codeType.setType("hospital_level");
                JyCodeType hospitalLevel = jyCodeTypeMapper.selectOne(codeType);

                entity.setType(hospitalLevel.getId());
                entity.setCode(form.getApplyHospitalLevel().toString());
                jyCode = jyCodeMapper.selectOne(entity);
                form.setApplyHospitalLevelDesc(jyCode.getName());
            }


            //报单科室
            if(form.getApplyOffice() != null){

                codeType.setType("hospital_office");
                JyCodeType hospitalOffice = jyCodeTypeMapper.selectOne(codeType);

                entity.setType(hospitalOffice.getId());
                entity.setCode(form.getApplyOffice().toString());
                jyCode = jyCodeMapper.selectOne(entity);
                form.setApplyOfficeName(jyCode.getName());
            }

            //申请经销商
            if(form.getApplyDealerId() != null){

                Dealer dealer = dealerMapper.selectById(form.getApplyDealerId());
                form.setApplyDealerName(dealer.getName());
            }

            //申请人员
            if(form.getApplyDealerUserId() != null){

                JyUser dealUser = jyUserMapper.selectById(form.getApplyDealerUserId());
                form.setApplyDealerUserName(dealUser.getName());
            }

            //申请状态
            if(form.getApplyStatus() != null){

                codeType.setType("declaration_form_status");
                JyCodeType declarationFormStatus = jyCodeTypeMapper.selectOne(codeType);

                entity.setType(declarationFormStatus.getId());
                entity.setCode(form.getApplyStatus().toString());
                jyCode = jyCodeMapper.selectOne(entity);
                form.setApplyStatusDesc(jyCode.getName());
            }

            //审核人
            if(form.getAuditUserId() != null){

                JyUser auditUser = jyUserMapper.selectById(form.getAuditUserId());
                form.setAuditUserName(auditUser.getName());
            }

            //撤销人
            if(form.getRevokeUserId() != null){

                JyUser revokeUser = jyUserMapper.selectById(form.getRevokeUserId());
                form.setRevokeUserName(revokeUser.getName());
            }

        }

        return form;
    }

    /**
     * 查询报单状态
     * @param applyHospitalId
     * @param applyOffice
     * @param status
     * @return
     */
    private List<JyDeclarationForm> queryApplyStatus(Long applyHospitalId, Long applyOffice,Long status){

        Wrapper<JyDeclarationForm> wrapper = new EntityWrapper<>();
        wrapper.eq("apply_hospital_id",applyHospitalId);
        wrapper.eq("apply_office",applyOffice);
        wrapper.eq("apply_status ",status);//报单状态，待审核、审核通过

        return jyDeclarationFormMapper.selectList(wrapper);
    }
    /**
     * 查询位置相似度较高的已经报单的医院科室
     * @param applyOffice
     * @return
     */
    private List<JyDeclarationForm> queryApplyStatus(Long applyOffice,JyDeclarationForm jyDeclarationForm){

        Wrapper<JyDeclarationForm> wrapper = new EntityWrapper<>();
        wrapper.where("apply_hospital_id IS NULL AND apply_office = "+applyOffice);
        List<JyDeclarationForm> forms = jyDeclarationFormMapper.selectList(wrapper);
        List<JyDeclarationForm> ratioForms = new ArrayList<>();

        if (forms != null && forms.size()>0){

            for (JyDeclarationForm form : forms) {
                float ratio = AdscmBaseUtils.getInstance().getSimilarityRatio(jyDeclarationForm.getApplyAddressSheng(), form.getApplyAddressSheng());
                if (ratio == 1.0){
                    ratio = AdscmBaseUtils.getInstance().getSimilarityRatio(jyDeclarationForm.getApplyAddressShi(), form.getApplyAddressShi());
                    if (ratio == 1.0){
                        ratio = AdscmBaseUtils.getInstance().getSimilarityRatio(jyDeclarationForm.getApplyAddressQuxian(), form.getApplyAddressQuxian());
                        if (ratio == 1.0){
                            ratio = AdscmBaseUtils.getInstance().getSimilarityRatio(jyDeclarationForm.getApplyAddressDetail(), form.getApplyAddressDetail());
                            if (ratio > 0.5){
                                //有个对于这个科室的报单申请的地理位置相似，则返回
                                ratioForms.add(form);
                            }
                        }
                    }
                }
            }
        }
        return ratioForms;
    }


    private SimpleCoreResponse loadResponse(List<JyDeclarationForm> ratioForms){
        StringBuffer names = new StringBuffer();
        for (JyDeclarationForm ratioForm : ratioForms) {
            names.append(ratioForm.getApplyHospitalName());
            names.append("、");
        }
        return new SimpleCoreResponse("300","存在与当前报单医院地址相似度较高的其他医院的当前科室，其他经销商也正在报单，在等待厂商审核， 是否继续报单 ？" +
                "<br/> 其他相似医院：【"+names.substring(0,names.length()-1)+"】" +
                "<br/> （如果继续报单，厂商可能会审核通过其他经销商的报单申请，系统无法保证您可以报单成功！）",0);
    }

    @Override
    public SimpleCoreResponse queryApplyFormStatus(JyDeclarationForm jyDeclarationForm)  throws AdscmSystemException{

        logger.info("查询报单状态");

        Long applyHospitalId = jyDeclarationForm.getApplyHospitalId();
        Long applyOffice = jyDeclarationForm.getApplyOffice();//科室
        Integer dealerId = jyDeclarationForm.getApplyDealerId();//申请经销商

        if (applyOffice == null){
           throw new AdscmSystemException("请选择科室！");
        }

        if (applyHospitalId != null && applyHospitalId > 0){
            //证明是选择的医院
            //看已经存在于系统的医院中，有没有相同科室的报单

            List<JyDeclarationForm> formList = this.queryApplyStatus(applyHospitalId, applyOffice, 1L);//审核通过

            if (formList != null && formList.size() > 0){
                for (JyDeclarationForm form : formList) {
                    Integer applyDealerId = form.getApplyDealerId();
                    if (applyDealerId != null && dealerId.intValue() == applyDealerId.intValue()){
                        throw  new AdscmSystemException("当前医院的当前科室已经被您报过单了，不能重复报单！）");
                    }
                }

                return new SimpleCoreResponse("300","当前医院的当前科室已经被其他经销商报单成功了， 是否继续报单 ？" +
                        "<br/>（如果继续报单，则报单申请则会加入报单意向队列中，如果当前报单的经销商后续退出此医院的报单，厂商可能会重新审核您的报单申请！）",4);
            }else {
                formList = this.queryApplyStatus(applyHospitalId, applyOffice, 0L);//待审核
                if (formList != null && formList.size() > 0){
                    for (JyDeclarationForm form : formList) {
                        Integer applyDealerId = form.getApplyDealerId();
                        if (applyDealerId != null && dealerId.intValue() == applyDealerId.intValue()){
                            throw  new AdscmSystemException("当前医院的当前科室已经被您报过单了，不能重复报单！）");
                        }
                    }
                    return new SimpleCoreResponse("300","当前医院的当前科室，有其他经销商也在报单，在等待厂商审核， 是否继续报单 ？" +
                            "<br/> （如果继续报单，厂商可能会审核通过其他经销商的报单申请，系统无法保证您可以报单成功！）",0);
                }else {
                    //在已经存在系统中的医院，不存在有经销商报这个科室的单
                    // 查询所有经销商新申请的医院有没有相似度较高的医院，报的这个科室的
                    List<JyDeclarationForm> ratioForms = this.queryApplyStatus(applyOffice, jyDeclarationForm);

                    if (ratioForms != null && ratioForms.size()>0){

                        return this.loadResponse(ratioForms);

                    }else {
                        return new SimpleCoreResponse("200","可以报单",0);
                    }

                }

            }

        }else {
            //证明是手动录入的医院

            //首先看所有手动录入医院有没有相似的
            List<JyDeclarationForm> ratioForms = this.queryApplyStatus(applyOffice, jyDeclarationForm);
            if (ratioForms != null && ratioForms.size()>0){
                return this.loadResponse(ratioForms);
            }else {
                //手动录的医院没有，再看系统存在的所有医院
                List<JyHospitalBase> allHospitalNameList = jyHospitalBaseMapper.queryAllHospitalNameList();
                    //循环计算每个医院和录入的医院的相似度

                List<JyDeclarationForm> auditPass = new ArrayList<>();//审核通过的
                List<JyDeclarationForm> auditing = new ArrayList<>();//待审核的

                for (JyHospitalBase jyHospitalBase : allHospitalNameList) {

                    float ratio = AdscmBaseUtils.getInstance().getSimilarityRatio(jyDeclarationForm.getApplyAddressSheng(), jyHospitalBase.getAddressSheng());
                    if (ratio == 1.0){
                        ratio = AdscmBaseUtils.getInstance().getSimilarityRatio(jyDeclarationForm.getApplyAddressShi(), jyHospitalBase.getAddressShi());
                        if (ratio == 1.0){
                            ratio = AdscmBaseUtils.getInstance().getSimilarityRatio(jyDeclarationForm.getApplyAddressQuxian(), jyHospitalBase.getAddressQuxian());
                            if (ratio == 1.0){
                                //只有当省市区县都匹配上了，才匹配最后的详细地址，看详细地址的相似度，相似度大于 0.5 的，再查询这个医院，有没有和当前申请的科室一样的科室
                                ratio = AdscmBaseUtils.getInstance().getSimilarityRatio(jyDeclarationForm.getApplyAddressDetail(), jyHospitalBase.getAddressDetail());

                                if (ratio > 0.4){
                                    //查询这个医院的这个科室是否被报过单
                                    Long hospitalBaseId = jyHospitalBase.getId();//医院ID

                                    List<JyDeclarationForm> formList = this.queryApplyStatus(hospitalBaseId, applyOffice, 1L);//审核通过
                                    if (formList != null && formList.size()>0){
                                        auditPass.addAll(formList);
                                    }
                                    List<JyDeclarationForm> formList1 = this.queryApplyStatus(hospitalBaseId, applyOffice, 0L);//待审核
                                    if (formList1 != null && formList1.size()>0){
                                        auditing.addAll(formList1);
                                    }


                                }

                            }
                        }
                    }

                }

                if (auditPass.size()==0 && auditing.size()==0){
                    //可以直接报单
                    return new SimpleCoreResponse("200","可以报单",0);
                }else {
                    if(auditPass.size()>0 && auditing.size()>0){

                        StringBuffer names1 = new StringBuffer();
                        for (JyDeclarationForm pass : auditPass) {
                            names1.append(pass.getApplyHospitalName());
                            names1.append("、");
                        }
                        StringBuffer names2 = new StringBuffer();
                        for (JyDeclarationForm pass : auditing) {
                            names2.append(pass.getApplyHospitalName());
                            names2.append("、");
                        }
                        return new SimpleCoreResponse("300","存在与当前报单医院地址相似度较高的其他医院的当前科室，其他经销商也正在报单， 是否继续报单 ？" +
                                "<br/> 审核通过的报单医院：【"+names1.substring(0,names1.length()-1)+"】" +
                                "<br/> 等待审核的报单医院：【"+names2.substring(0,names2.length()-1)+"】" +
                                "<br/> （如果继续报单，厂商可能不会审核通过您的报单申请，系统无法保证您可以报单成功！）",0);
                    }else {
                        if (auditPass.size()>0){
                            StringBuffer names = new StringBuffer();
                            for (JyDeclarationForm pass : auditPass) {
                                names.append(pass.getApplyHospitalName());
                                names.append("、");
                            }
                            return new SimpleCoreResponse("300","存在与当前报单医院地址相似度较高的其他医院的当前科室，其他经销商也正在报单并审核通过， 是否继续报单 ？" +
                                    "<br/> 审核通过的报单医院：【"+names.substring(0,names.length()-1)+"】" +
                                    "<br/> （如果继续报单，厂商可能不会审核通过您的报单申请，系统无法保证您可以报单成功！）",0);
                        }else {
                            StringBuffer names = new StringBuffer();
                            for (JyDeclarationForm pass : auditing) {
                                names.append(pass.getApplyHospitalName());
                                names.append("、");
                            }
                            return new SimpleCoreResponse("300","存在与当前报单医院地址相似度较高的其他医院的当前科室，其他经销商也正在报单并等待审核， 是否继续报单 ？" +
                                    "<br/> 等待审核的报单医院：【"+names.substring(0,names.length()-1)+"】" +
                                    "<br/> （如果继续报单，厂商可能不会审核通过您的报单申请，系统无法保证您可以报单成功！）",0);
                        }


                    }
                }


            }


        }
    }

    @Override
    public List<JyDeclarationForm> selectAll(JyUser user)throws AdscmSystemException  {

        if (user == null){
            throw new AdscmSystemException("没有获取到登录信息，请重新登录！");
        }
        boolean hasRole = AdscmSecurityUtils.getInstance().hasRole("ROLE_dealer_declaration_admin", user);

        List<Integer> dealerIds = null;
        if (!hasRole){
            Wrapper<Dealer> wrapper = new EntityWrapper<>();
            wrapper.eq("jy_manager",user.getId());
            List<Dealer> dealers = dealerMapper.selectList(wrapper);

            if (dealers != null && dealers.size()>0){
                dealerIds = new ArrayList<>();
                for (Dealer dealer : dealers) {
                    dealerIds.add(dealer.getId());
                }
            }
        }
        return jyDeclarationFormMapper.selectAll(dealerIds);
    }


}
